﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Ports;
using System.Text;
using System.Threading;

/// <summary>
/// 工具集
/// </summary>
namespace Utils
{
    /// <summary>
    /// 智能串口类
    /// </summary>
    public class SmartSerialPort
    {
        /* 串口类 */
        private SerialPort _serialPort = new SerialPort();
        /* 是否开始接收数据 */
        private bool IsReceiveStart = false;
        /* 接收数据线程 */
        private Thread receiveThread;
        /* 延时时间，10 * 100 * 0.1us = 100us */
        private TimeSpan delayTime = new TimeSpan(10 * 100);
        /* 接收数据超时事件，单位ms */
        private int _ReceiveTimeOut = 3;
        /* 事件信号量 */
        private ManualResetEvent uartReceivedEvent = new ManualResetEvent(false);
        /* 数据接收完成处理事件委托模型声明 */
        public delegate void ReceiveFinishedEventHandler(object sender, SmartSerialPortReceiveFrame frame);
        /* 创建接收完成事件 */
        public event ReceiveFinishedEventHandler ReceiveFinishedEvent;
        /* 是否处于接收数据中 */
        bool is_receiving = false;
        /* 接收帧 */
        SmartSerialPortReceiveFrame rx_frame = new SmartSerialPortReceiveFrame(null);

        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="sp">串口对象</param>
        public SmartSerialPort(SerialPort sp)
        {
            _serialPort = sp;
        }

        /// <summary>
        /// 串口对象读写操作
        /// </summary>
        public SerialPort serialPort
        {
            get { return _serialPort; }
            set { _serialPort = value; }
        }

        /// <summary>
        /// 超时时间读写操作
        /// </summary>
        public int ReceiveTimeOut
        {
            get { return _ReceiveTimeOut; }
            set { _ReceiveTimeOut = value; }
        }

        /// <summary>
        /// 终止莫个线程
        /// </summary>
        /// <param name="th"></param>
        private void StopThread(Thread th)
        {
            try
            {
                if (th != null)
                {
                    lock (th)
                    {
                        if (th.IsAlive)
                        {
                            th.Abort();
                        }
                    }
                }
            }
            catch (System.Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
        }

        /// <summary>
        /// 启动串口
        /// </summary>
        public void Start()
        {
            try
            {
                /* 启动接收处理 */
                IsReceiveStart = true;

                if (serialPort.IsOpen)
                {
                    serialPort.Close();
                }
                serialPort.Open();
                serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);

                StopThread(receiveThread);

                receiveThread = new Thread(new ThreadStart(ReceiveThreadHandler));
                receiveThread.IsBackground = true;
                receiveThread.Name = "receiveThread";
                receiveThread.Start();
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 停止串口
        /// </summary>
        public void Stop()
        {
            try
            {
                /* 停止接收 */
                IsReceiveStart = false;

                if (serialPort != null)
                {
                    lock (serialPort)
                    {
                        serialPort.DataReceived -= new SerialDataReceivedEventHandler(serialPort_DataReceived);
                        if (serialPort.IsOpen)
                        {
                            serialPort.Close();
                        }

                    }
                }
                StopThread(receiveThread);

            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 接收数据处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (uartReceivedEvent != null)
            {
                /* 设置信号量，收到数据 */
                uartReceivedEvent.Set();
            }
        }

        /// <summary>
        /// 接收线程
        /// </summary>
        private void ReceiveThreadHandler()
        {
            while (IsReceiveStart)
            {
                try
                {
                    if (_serialPort.IsOpen)
                    {
                        try
                        {
                            int dataLen;
                            if (uartReceivedEvent.WaitOne())
                            {
                                if (is_receiving == false)
                                {
                                    is_receiving = true;
                                    rx_frame.Time = DateTime.Now;
                                }
                                uartReceivedEvent.Reset();

                                int buffSize = 0;
                                do
                                {
                                    buffSize = serialPort.BytesToRead;
                                    Thread.Sleep(ReceiveTimeOut);

                                } while (buffSize != serialPort.BytesToRead);

                                is_receiving = false;
                                if (buffSize > 0)
                                {
                                    byte[] receiveBytes = new byte[buffSize];
                                    dataLen = serialPort.Read(receiveBytes, 0, receiveBytes.Length);
                                    if (dataLen > 0)
                                    {
                                        byte[] bytes = new byte[dataLen];
                                        Array.Copy(receiveBytes, bytes, dataLen);
                                        /* 调用委托函数 */
                                        //ReceiveFinishedEvent?.Invoke(this, new SmartSerialPortReceiveFrame(bytes));
                                        rx_frame.Data = bytes;
                                        ReceiveFinishedEvent?.BeginInvoke(this, rx_frame, null, new object[] { null });
                                    }
                                }
                            }
                        }
                        catch (System.Exception ex)
                        {
                            Debug.WriteLine(ex.ToString());
                        }
                    }
                    else
                    {
                        Thread.Sleep(10);
                    }
                }
                catch (System.Exception ex)
                {
                    Debug.WriteLine(ex.ToString());
                }
            }
        }
    }

    /// <summary>
    /// 智能串口接收数据包
    /// </summary>
    public class SmartSerialPortReceiveFrame
    {
        /* 接收时间 */
        private DateTime _time;
        /* 接收数据 */
        private byte[] _data;
        /* 数据长度 */
        private int _length;

        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="data">数据</param>
        public SmartSerialPortReceiveFrame(byte[] data)
        {
            _data = data;
            _time = DateTime.Now;
            if (data != null)
            {
                _length = data.Length;
            }
            else
            {
                _length = 0;
            }
        }

        /// <summary>
        /// 读取数据
        /// </summary>
        public byte[] Data
        {
            set { _data = value; }
            get { return _data; }
        }

        /// <summary>
        /// 读取时间
        /// </summary>
        public DateTime Time
        {
            set { _time = value; }
            get { return _time; }
        }

        /// <summary>
        /// 读取数据长度
        /// </summary>
        public int Length
        {
            set { _length = value; }
            get { return _length; }
        }

        /// <summary>
        /// 获取时间字符串
        /// </summary>
        public string TimeString
        {
            get
            {
                return string.Format("[{0}.{1:D3}]", _time.ToString("yyyy-MM-dd HH:mm:ss"), _time.Millisecond);
            }
        }

        public string HexString
        {
            get
            {
                return string.Format("{0} ", BitConverter.ToString(_data).Replace('-', ' '));
            }
        }

        public string AsciiString
        {
            get
            {
                return StreamConverter.ArrayToAsciiString(Encoding.UTF8, _data);
            }
        }

        public string DecString
        {
            get
            {
                StringBuilder sb = new StringBuilder();

                foreach (byte b in _data)
                {
                    sb.AppendFormat("{0} ", Convert.ToInt32(b));
                }

                return sb.ToString();
            }
        }
    }
}
